package service

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/google/uuid"
	"gorm.io/gorm"
	"service/basic/global"
	__ "service/basic/proto"
	"service/internal/model"
	"service/pkg"
	"time"
)

type Service struct {
	__.UnimplementedTakeOutServer
}

func (s *Service) CreateOrder(_ context.Context, req *__.CreateOrderReq) (resp *__.CreateOrderResp, err error) {
	goods := model.Goods{}

	global.DB.Debug().Where("id = ?", req.GoodsId).First(&goods)
	if goods.ID == 0 {
		return nil, err
	}

	if req.Quantity > goods.Stock {
		return nil, fmt.Errorf("当前商品库存不足")
	}

	if req.Address == "" {
		return nil, fmt.Errorf("请填写收货地址")
	}

	if float64(req.Price) != goods.Price {
		return nil, fmt.Errorf("支付价格与商品不匹配")
	}

	OrderSn := GetOrderSn()

	order := model.Order{
		UserId:     req.UserId,
		GoodsId:    req.GoodsId,
		MerchantId: req.MerchantId,
		OrderSn:    OrderSn,
		Quantity:   req.Quantity,
		Price:      float64(req.Price),
		Address:    req.Address,
		Status:     req.Status,
	}

	err = global.DB.Debug().Create(&order).Error
	if err != nil {
		return nil, fmt.Errorf("订单创建失败")
	}

	url, err := pkg.AliPay(OrderSn, order.Price)
	if err != nil {
		return nil, fmt.Errorf("支付创建失败")
	}

	pkg.QrcodeCreate()

	err = global.DB.Debug().Model(&model.Goods{}).Where("id = ?", req.GoodsId).Update("stock", goods.Stock-req.Quantity).Error

	if err != nil {
		return nil, fmt.Errorf("库存更新失败")
	}

	resp = &__.CreateOrderResp{
		Id:      int64(order.ID),
		Success: true,
		Message: "订单创建成功",
		OrderSn: order.OrderSn,
		Url:     url,
	}

	return resp, nil
}

func GetOrderSn() string {
	str := uuid.NewString()
	return str
}

func (s *Service) OrderList(_ context.Context, req *__.OrderListReq) (resp *__.OrderListResp, err error) {

	var orders []model.Order

	tx := global.DB.Debug().Model(&model.Order{})

	if req.OrderByTime == true {
		tx = tx.Order("created_at desc")
	}

	tx.Scopes(Paginate(req.Page, req.Size)).Find(&orders)

	var orderList []*__.OrderItem
	for _, order := range orders {
		list := __.OrderItem{
			Id:         int64(order.ID),
			UserId:     order.UserId,
			GoodsId:    order.GoodsId,
			Quantity:   order.Quantity,
			Address:    order.Address,
			Price:      float32(order.Price),
			OrderSn:    order.OrderSn,
			Status:     order.Status,
			MerchantId: order.MerchantId,
		}

		orderList = append(orderList, &list)
	}
	resp = &__.OrderListResp{
		List: orderList,
	}

	return resp, nil

}

func Paginate(page, size int64) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {

		if page <= 0 {
			page = 1
		}

		switch {
		case size > 100:
			size = 100
		case size <= 0:
			size = 10
		}

		offset := (page - 1) * size
		return db.Offset(int(offset)).Limit(int(size))
	}
}

func (s *Service) RiderOrderList(_ context.Context, req *__.RiderOrderListReq) (resp *__.RiderOrderListResp, err error) {
	var orders []model.Order

	err = global.DB.Debug().Model(&model.Order{}).Where("status", req.Status).Find(&orders).Error

	if err != nil {
		return nil, fmt.Errorf("订单查询失败")
	}

	var orderList []*__.OrderItem
	for _, order := range orders {
		list := __.OrderItem{
			Id:         int64(order.ID),
			UserId:     order.UserId,
			GoodsId:    order.GoodsId,
			Quantity:   order.Quantity,
			Address:    order.Address,
			Price:      float32(order.Price),
			OrderSn:    order.OrderSn,
			Status:     order.Status,
			MerchantId: order.MerchantId,
		}

		orderList = append(orderList, &list)
	}
	resp = &__.RiderOrderListResp{
		List: orderList,
	}

	key := "rider_order"

	data, err := json.Marshal(&resp)
	if err != nil {
		return nil, err
	}

	err = global.Rdb.Set(global.Ctx, key, data, time.Minute*10).Err()
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func (s *Service) UserOrderList(_ context.Context, req *__.UserOrderListReq) (resp *__.UserOrderListResp, err error) {
	var orders []model.Order

	err = global.DB.Debug().Model(&model.Order{}).Where("user_id", req.UserId).Find(&orders).Error

	if err != nil {
		return nil, fmt.Errorf("订单查询失败")
	}

	var orderList []*__.OrderItem
	for _, order := range orders {
		list := __.OrderItem{
			Id:         int64(order.ID),
			UserId:     order.UserId,
			GoodsId:    order.GoodsId,
			Quantity:   order.Quantity,
			Address:    order.Address,
			Price:      float32(order.Price),
			OrderSn:    order.OrderSn,
			Status:     order.Status,
			MerchantId: order.MerchantId,
		}

		orderList = append(orderList, &list)
	}
	resp = &__.UserOrderListResp{
		List: orderList,
	}

	return resp, nil
}

func (s *Service) MerchantOrderList(_ context.Context, req *__.MerchantOrderListReq) (resp *__.MerchantOrderListResp, err error) {
	var orders []model.Order

	err = global.DB.Debug().Model(&model.Order{}).Where("merchant_id", req.MerchantId).Find(&orders).Error

	if err != nil {
		return nil, fmt.Errorf("订单查询失败")
	}

	var orderList []*__.OrderItem
	for _, order := range orders {
		list := __.OrderItem{
			Id:         int64(order.ID),
			UserId:     order.UserId,
			GoodsId:    order.GoodsId,
			Quantity:   order.Quantity,
			Address:    order.Address,
			Price:      float32(order.Price),
			OrderSn:    order.OrderSn,
			Status:     order.Status,
			MerchantId: order.MerchantId,
		}

		orderList = append(orderList, &list)
	}
	resp = &__.MerchantOrderListResp{
		List: orderList,
	}

	return resp, nil
}

func (s *Service) RiderRank(_ context.Context, req *__.RiderRankReq) (resp *__.RiderRankResp, err error) {
	var riders []model.Rider

	err = global.DB.Debug().Model(&model.Rider{}).Order("num desc").Find(&riders).Error

	if err != nil {
		return nil, fmt.Errorf("排行榜查询失败")
	}

	var rankList []*__.RankItem
	for _, rider := range riders {
		list := __.RankItem{
			Id:   int64(rider.ID),
			Name: rider.Name,
			Num:  rider.Num,
		}

		rankList = append(rankList, &list)
	}
	resp = &__.RiderRankResp{
		List: rankList,
	}

	return resp, nil
}

func (s *Service) MerchantList(_ context.Context, req *__.MerchantListReq) (resp *__.MerchantListResp, err error) {
	var merchants []model.Merchant

	tx := global.DB.Debug().Model(&model.Merchant{})

	if req.Title != "" {
		tx = tx.Where("title like ?", "%"+req.Title+"%")
	}

	tx.Order("score desc").Find(&merchants)

	var merchantList []*__.MerchantItem
	for _, merchant := range merchants {
		list := __.MerchantItem{
			Id:        int64(merchant.ID),
			Title:     merchant.Title,
			Introduce: merchant.Introduce,
			Score:     float32(merchant.Score),
		}

		merchantList = append(merchantList, &list)
	}
	resp = &__.MerchantListResp{
		List: merchantList,
	}

	return resp, nil

}

func (s *Service) CreateAppointment(_ context.Context, req *__.CreateAppointmentReq) (resp *__.CreateAppointmentResp, err error) {

	appointment := model.Appointment{
		MerchantId: req.MerchantId,
		UserId:     req.UserId,
		Date:       req.Date,
		Num:        req.Num,
		Mobile:     req.Mobile,
	}

	err = global.DB.Debug().Create(&appointment).Error
	if err != nil {
		return nil, fmt.Errorf("预约失败")
	}

	pkg.QrcodeCreate()

	resp = &__.CreateAppointmentResp{
		Id:      int64(appointment.ID),
		Success: true,
		Message: "预约成功",
	}

	return resp, err
}

func (s *Service) AppointmentList(_ context.Context, req *__.AppointmentListReq) (resp *__.AppointmentListResp, err error) {

	var appointments []model.Appointment

	tx := global.DB.Debug().Model(&model.Appointment{})

	if req.OrderByTime == true {
		tx = tx.Order("created_at desc")
	}

	tx.Find(&appointments)

	var orderList []*__.AppointmentItem
	for _, appointment := range appointments {
		list := __.AppointmentItem{
			Id:         int64(appointment.ID),
			MerchantId: appointment.MerchantId,
			UserId:     appointment.UserId,
			Date:       appointment.Date,
			Num:        appointment.Num,
			Mobile:     appointment.Mobile,
		}

		orderList = append(orderList, &list)
	}
	resp = &__.AppointmentListResp{
		List: orderList,
	}

	return resp, nil

}

func (s *Service) AppointmentUpdate(_ context.Context, req *__.AppointmentUpdateReq) (resp *__.AppointmentUpdateResp, err error) {

	appointment := model.Appointment{}

	err = global.DB.Debug().Where("id=?", req.Id).First(&appointment).Error

	if err != nil {
		return nil, err
	}

	err = global.DB.Debug().Model(&model.Appointment{}).Where("id =?", req.Id).Update("status", req.Status).Error
	if err != nil {
		return nil, fmt.Errorf("更新失败")
	}

	resp = &__.AppointmentUpdateResp{
		Id:      int64(appointment.ID),
		Success: true,
		Message: "更新成功",
	}

	return resp, err
}

func (s *Service) CommentAdd(_ context.Context, req *__.CommentAddReq) (resp *__.CommentAddResp, err error) {

	comment := model.Comment{
		MerchantId: req.MerchantId,
		UserId:     req.UserId,
		Context:    req.Context,
	}

	err = global.DB.Debug().Create(&comment).Error
	if err != nil {
		return nil, fmt.Errorf("评论失败")
	}

	pkg.QrcodeCreate()

	resp = &__.CommentAddResp{
		Id:      int64(comment.ID),
		Success: true,
		Message: "评论成功",
	}

	return resp, err
}

func (s *Service) CommentList(_ context.Context, req *__.CommentListReq) (resp *__.CommentListResp, err error) {

	var comments []model.Comment

	err = global.DB.Debug().Where("merchant_id=?", req.MerchantId).Find(&comments).Error

	var commentList []*__.CommentItem
	for _, comment := range comments {
		list := __.CommentItem{
			Id:         comment.UserId,
			MerchantId: comment.MerchantId,
			UserId:     comment.UserId,
			Context:    comment.Context,
		}

		commentList = append(commentList, &list)
	}
	resp = &__.CommentListResp{
		List: commentList,
	}

	return resp, nil

}

func (s *Service) GoodsList(_ context.Context, req *__.GoodsListReq) (resp *__.GoodsListResp, err error) {

	var goods []model.Goods

	err = global.DB.Debug().Where("merchant_id=?", req.MerchantId).Order("sale desc").Find(&goods).Error

	var goodsList []*__.GoodsItem
	for _, good := range goods {
		list := __.GoodsItem{
			Name:      good.Name,
			Introduce: good.Introduce,
			Price:     float32(good.Price),
			Stock:     good.Stock,
			Status:    good.Status,
		}

		goodsList = append(goodsList, &list)
	}
	resp = &__.GoodsListResp{
		List: goodsList,
	}

	key := "goods_list"

	data, err := json.Marshal(&resp)
	if err != nil {
		return nil, err
	}

	err = global.Rdb.Set(global.Ctx, key, data, time.Minute*30).Err()
	if err != nil {
		return nil, err
	}

	return resp, nil

}

func (s *Service) AddressList(_ context.Context, req *__.AddressListReq) (resp *__.AddressListResp, err error) {

	var address []model.Address

	err = global.DB.Debug().Model(&model.Address{}).Where("name like ?", "%"+req.Name+"%").Find(&address).Error

	var addressList []*__.AddressItem
	for _, addr := range address {
		list := __.AddressItem{
			Id:            int64(addr.ID),
			Name:          addr.Name,
			BusinessHours: addr.BusinessHours,
		}

		addressList = append(addressList, &list)
	}
	resp = &__.AddressListResp{
		List: addressList,
	}

	return resp, nil

}

func (s *Service) OperateList(_ context.Context, req *__.OperateListReq) (resp *__.OperateListResp, err error) {

	var operates []model.Operate

	tx := global.DB.Debug().Model(&model.Operate{})

	if req.Name != "" {
		tx = tx.Where("name = ?", req.Name)
	}

	tx.Find(&operates)

	var operateList []*__.OperateItem
	for _, operate := range operates {
		list := __.OperateItem{
			Id:   int64(operate.ID),
			Name: operate.Name,
			Num:  operate.Num,
		}

		operateList = append(operateList, &list)
	}
	resp = &__.OperateListResp{
		List: operateList,
	}

	key := "operate_list"

	data, err := json.Marshal(&resp)
	if err != nil {
		return nil, err
	}

	err = global.Rdb.Set(global.Ctx, key, data, time.Hour*24).Err()
	if err != nil {
		return nil, err
	}

	return resp, nil

}
